<?php

namespace app\service\impl;

use app\popo\dto\OrdersCancelDTO;
use app\popo\dto\OrdersConfirmDTO;
use app\popo\dto\OrdersPageQueryDTO;
use app\popo\dto\OrdersPaymentDTO;
use app\popo\dto\OrdersRejectionDTO;
use app\popo\dto\OrdersSubmitDTO;
use app\popo\model\AddressBook;
use app\popo\model\Order;
use app\popo\model\OrderDetail;
use app\popo\model\ShoppingCart;
use app\popo\vo\OrderPaymentVO;
use app\popo\vo\OrderStatisticsVO;
use app\popo\vo\OrderSubmitVO;
use app\popo\vo\OrderVO;
use app\repository\OrderRepository;
use app\service\OrderService;
use app\support\JwtHelper;
use app\support\ListContainer;
use Carbon\Carbon;
use DI\Attribute\Inject;
use support\Db;
use support\exception\BusinessException;
use support\Log;
use Webman\Http\Request;

class OrderServiceImpl implements OrderService
{
    #[Inject]
    protected OrderRepository $orderRepository;

    public function conditionSearch(Request $request): array
    {
        return $this->orderRepository->conditionSearch($request);
    }

    /**
     * 用户下单
     * @param OrdersSubmitDTO $ordersSubmitDTO
     * @return OrderSubmitVO
     */
    public function submitOrder(OrdersSubmitDTO $ordersSubmitDTO): OrderSubmitVO
    {
        // 获取当前登录用户
        $user = JwtHelper::getUser();
        if (!$user->id) {
            throw new BusinessException('用户未登录');
        }

        // 获取地址信息
        $addressBook = AddressBook::find($ordersSubmitDTO->getAddressBookId());
        if (!$addressBook) {
            throw new BusinessException('地址信息不存在');
        }

        // 查询购物车中的商品
        $shoppingCartList = ShoppingCart::where('user_id', $user->id)->get();
        if ($shoppingCartList->isEmpty()) {
            throw new BusinessException('购物车为空，不能下单');
        }

        // 计算订单金额
        $totalAmount = $ordersSubmitDTO->getAmount();

        // 生成订单号
        $orderNumber = (string) (microtime(true) * 10000);

        // 开启事务
        return Db::transaction(function () use ($ordersSubmitDTO, $user, $addressBook, $shoppingCartList, $totalAmount, $orderNumber) {
            // 插入订单数据
            $order = new Order();
            $order->number = $orderNumber;
            $order->status = 1; // 待付款
            $order->user_id = $user->id;
            $order->address_book_id = $ordersSubmitDTO->getAddressBookId();
            $order->order_time = Carbon::now()->toDateTimeString();
            $order->pay_method = $ordersSubmitDTO->getPayMethod();
            $order->pay_status = 0; // 未支付
            $order->amount = $totalAmount;
            $order->remark = $ordersSubmitDTO->getRemark();
            $order->phone = $addressBook->phone;
            $order->address = $addressBook->detail;
            $order->user_name = $user->name ?? '';
            $order->consignee = $addressBook->consignee;
            $order->estimated_delivery_time = $ordersSubmitDTO->getEstimatedDeliveryTime();
            $order->delivery_status = $ordersSubmitDTO->getDeliveryStatus();
            $order->pack_amount = $ordersSubmitDTO->getPackAmount();
            $order->tableware_number = $ordersSubmitDTO->getTablewareNumber();
            $order->tableware_status = $ordersSubmitDTO->getTablewareStatus();
            $order->save();

            // 插入订单明细数据
            foreach ($shoppingCartList as $shoppingCart) {
                $orderDetail = new OrderDetail();
                $orderDetail->order_id = $order->id;
                $orderDetail->name = $shoppingCart->name;
                $orderDetail->image = $shoppingCart->image;
                $orderDetail->dish_id = $shoppingCart->dish_id;
                $orderDetail->setmeal_id = $shoppingCart->setmeal_id;
                $orderDetail->dish_flavor = $shoppingCart->dish_flavor;
                $orderDetail->number = $shoppingCart->number;
                $orderDetail->amount = $shoppingCart->amount;
                $orderDetail->save();
            }

            // 清空购物车
            ShoppingCart::where('user_id', $user->id)->delete();

            // 返回结果
            $orderSubmitVO = new OrderSubmitVO();
            $orderSubmitVO->setId($order->id);
            $orderSubmitVO->setOrderNumber($orderNumber);
            $orderSubmitVO->setOrderAmount($totalAmount);
            $orderSubmitVO->setOrderTime($order->order_time);

            return $orderSubmitVO;
        });
    }

    /**
     * 订单支付
     * @param OrdersPaymentDTO $ordersPaymentDTO
     * @return OrderPaymentVO
     */
    public function payment(OrdersPaymentDTO $ordersPaymentDTO): OrderPaymentVO
    {
        // 查询订单
        $order = Order::where('number', $ordersPaymentDTO->getOrderNumber())->first();
        if (!$order) {
            throw new BusinessException('订单不存在');
        }

        // 检查订单状态
        if ($order->status != 1) {
            throw new BusinessException('订单状态异常');
        }

        // 这里模拟微信支付，实际上应该调用微信支付API
        // 直接更新订单为已支付状态
        $order->pay_status = 1; // 已支付
        $order->status = 2; // 待接单
        $order->checkout_time = Carbon::now()->toDateTimeString();
        $order->save();

        // 返回模拟的支付信息
        $orderPaymentVO = new OrderPaymentVO();
        $orderPaymentVO->setNonceStr(uniqid());
        $orderPaymentVO->setPaySign('pay_sign_' . time());
        $orderPaymentVO->setTimeStamp((string)time());
        $orderPaymentVO->setSignType('MD5');
        $orderPaymentVO->setPackageStr('prepay_id=' . uniqid());

        return $orderPaymentVO;
    }

    /**
     * 历史订单查询
     * @param int $page
     * @param int $pageSize
     * @param int|null $status
     * @return ListContainer
     */
    public function pageQuery4User(int $page, int $pageSize, ?int $status): ListContainer
    {
        $user = JwtHelper::getUser();
        if (!$user->id) {
            throw new BusinessException('用户未登录');
        }

        $query = Order::where('user_id', $user->id);
        
        if ($status !== null) {
            $query->where('status', $status);
        }
        
        $query->orderByDesc('order_time');
        
        $paginator = $query->paginate($pageSize, ['*'], 'page', $page);
        
        return new ListContainer($paginator, function (Order $order) {
            return $this->buildOrderVO($order, true);
        });
    }

    /**
     * 查询订单详情
     * @param int $id
     * @return OrderVO
     */
    public function details(int $id): OrderVO
    {
        $order = Order::where('id', $id)->first();

        if (!$order) {
            throw new BusinessException('订单不存在');
        }

        return $this->buildOrderVO($order, true);
    }

    /**
     * 用户取消订单
     * @param int $id
     * @return void
     */
    public function userCancelById(int $id): void
    {
        $user = JwtHelper::getUser();
        if (!$user->id) {
            throw new BusinessException('用户未登录');
        }

        $order = Order::where('id', $id)
            ->where('user_id', $user->id)
            ->first();
        
        if (!$order) {
            throw new BusinessException('订单不存在');
        }

        // 检查订单状态，只有待付款和待接单的订单可以取消
        if (!in_array($order->status, [1, 2])) {
            throw new BusinessException('订单状态异常，不能取消');
        }

        $order->status = 6; // 已取消
        $order->cancel_reason = '用户取消';
        $order->cancel_time = Carbon::now()->toDateTimeString();
        $order->save();

        // 如果订单已支付，则需要退款操作（这里略过）
    }

    /**
     * 再来一单
     * @param int $id
     * @return void
     */
    public function repetition(int $id): void
    {
        $user = JwtHelper::getUser();
        if (!$user->id) {
            throw new BusinessException('用户未登录');
        }

        $order = Order::where('id', $id)
            ->where('user_id', $user->id)
            ->first();
        
        if (!$order) {
            throw new BusinessException('订单不存在');
        }

        // 获取订单详情
        $orderDetails = OrderDetail::where('order_id', $id)->get();
        
        if ($orderDetails->isEmpty()) {
            throw new BusinessException('订单详情不存在');
        }

        // 清空当前购物车
        ShoppingCart::where('user_id', $user->id)->delete();

        // 将订单详情加入购物车
        foreach ($orderDetails as $orderDetail) {
            $shoppingCart = new ShoppingCart();
            $shoppingCart->user_id = $user->id;
            $shoppingCart->dish_id = $orderDetail->dish_id;
            $shoppingCart->setmeal_id = $orderDetail->setmeal_id;
            $shoppingCart->name = $orderDetail->name;
            $shoppingCart->image = $orderDetail->image;
            $shoppingCart->amount = $orderDetail->amount;
            $shoppingCart->number = $orderDetail->number;
            $shoppingCart->dish_flavor = $orderDetail->dish_flavor;
            $shoppingCart->create_time = Carbon::now()->toDateTimeString();
            $shoppingCart->save();
        }
    }

    /**
     * 客户催单
     * @param int $id
     * @return void
     */
    public function reminder(int $id): void
    {
        $user = JwtHelper::getUser();
        if (!$user->id) {
            throw new BusinessException('用户未登录');
        }

        $order = Order::where('id', $id)
            ->where('user_id', $user->id)
            ->first();
        
        if (!$order) {
            throw new BusinessException('订单不存在');
        }

        // 检查订单状态，只有已接单和派送中的订单可以催单
        if (!in_array($order->status, [3, 4])) {
            throw new BusinessException('订单状态错误，不能催单');
        }

        // 这里可以发送催单通知给商家（通过WebSocket、短信等方式）
        // 这里暂时只做日志记录
        error_log("用户{$user->id}对订单{$id}进行了催单操作");
    }
    
    /**
     * 管理端订单条件搜索
     * @param OrdersPageQueryDTO $ordersPageQueryDTO
     * @return ListContainer
     */
    public function conditionSearchAdmin(OrdersPageQueryDTO $ordersPageQueryDTO): ListContainer
    {
        $query = Order::query();
        
        // 添加查询条件
        if ($ordersPageQueryDTO->number) {
            $query->where('number', 'like', '%' . $ordersPageQueryDTO->number . '%');
        }
        
        if ($ordersPageQueryDTO->phone) {
            $query->where('phone', $ordersPageQueryDTO->phone);
        }
        
        if ($ordersPageQueryDTO->status !== null) {
            $query->where('status', $ordersPageQueryDTO->status);
        }
        
        if ($ordersPageQueryDTO->beginTime) {
            $query->where('order_time', '>=', $ordersPageQueryDTO->beginTime);
        }
        
        if ($ordersPageQueryDTO->endTime) {
            $query->where('order_time', '<=', $ordersPageQueryDTO->endTime);
        }
        
        $query->orderByDesc('order_time');
        
        $paginator = $query->paginate(
            $ordersPageQueryDTO->pageSize, 
            ['*'], 
            'page', 
            $ordersPageQueryDTO->page
        );
        
        return new ListContainer($paginator, function (Order $order) {
            return $this->buildOrderVO($order, true);
        });
    }
    
    /**
     * 各个状态的订单数量统计
     * @return OrderStatisticsVO
     */
    public function statistics(): OrderStatisticsVO
    {
        $toBeConfirmed = Order::where('status', 2)->count(); // 待接单
        $confirmed = Order::where('status', 3)->count(); // 已接单
        $deliveryInProgress = Order::where('status', 4)->count(); // 派送中
        
        return new OrderStatisticsVO($toBeConfirmed, $confirmed, $deliveryInProgress);
    }
    
    /**
     * 接单
     * @param OrdersConfirmDTO $ordersConfirmDTO
     * @return void
     */
    public function confirm(OrdersConfirmDTO $ordersConfirmDTO): void
    {
        $order = Order::find($ordersConfirmDTO->id);
        if (!$order) {
            throw new BusinessException('订单不存在');
        }
        
        // 检查订单状态，只有待接单的订单可以接单
        if ($order->status != 2) {
            throw new BusinessException('订单状态错误，不能接单');
        }
        
        $order->status = 3; // 已接单
        $order->save();
    }
    
    /**
     * 拒单
     * @param OrdersRejectionDTO $ordersRejectionDTO
     * @return void
     */
    public function rejection(OrdersRejectionDTO $ordersRejectionDTO): void
    {
        $order = Order::find($ordersRejectionDTO->id);
        if (!$order) {
            throw new BusinessException('订单不存在');
        }
        
        // 检查订单状态，只有待接单的订单可以拒单
        if ($order->status != 2) {
            throw new BusinessException('订单状态错误，不能拒单');
        }
        
        $order->status = 6; // 已取消
        $order->rejection_reason = $ordersRejectionDTO->rejectionReason;
        $order->cancel_time = Carbon::now()->toDateTimeString();
        $order->save();
        
        // 如果订单已支付，需要退款（这里略过退款逻辑）
        if ($order->pay_status == 1) {
            // TODO: 实现退款逻辑
            Log::info("订单{$order->number}被拒绝，需要退款");
        }
    }
    
    /**
     * 取消订单
     * @param OrdersCancelDTO $ordersCancelDTO
     * @return void
     */
    public function cancel(OrdersCancelDTO $ordersCancelDTO): void
    {
        $order = Order::find($ordersCancelDTO->id);
        if (!$order) {
            throw new BusinessException('订单不存在');
        }
        
        // 检查订单状态，已完成的订单不能取消
        if ($order->status == 5) {
            throw new BusinessException('订单已完成，不能取消');
        }
        
        $order->status = 6; // 已取消
        $order->cancel_reason = $ordersCancelDTO->cancelReason;
        $order->cancel_time = Carbon::now()->toDateTimeString();
        $order->save();
        
        // 如果订单已支付，需要退款（这里略过退款逻辑）
        if ($order->pay_status == 1) {
            // TODO: 实现退款逻辑
            Log::info("订单{$order->number}被取消，需要退款");
        }
    }
    
    /**
     * 派送订单
     * @param int $id
     * @return void
     */
    public function delivery(int $id): void
    {
        $order = Order::find($id);
        if (!$order) {
            throw new BusinessException('订单不存在');
        }
        
        // 检查订单状态，只有已接单的订单可以派送
        if ($order->status != 3) {
            throw new BusinessException('订单状态错误，不能派送');
        }
        
        $order->status = 4; // 派送中
        $order->save();
    }
    
    /**
     * 完成订单
     * @param int $id
     * @return void
     */
    public function complete(int $id): void
    {
        $order = Order::find($id);
        if (!$order) {
            throw new BusinessException('订单不存在');
        }
        
        // 检查订单状态，只有派送中的订单可以完成
        if ($order->status != 4) {
            throw new BusinessException('订单状态错误，不能完成');
        }
        
        $order->status = 5; // 已完成
        $order->delivery_time = Carbon::now()->toDateTimeString();
        $order->save();
    }

    /**
     * 生成订单号
     * @return string
     */
    private function generateOrderNumber(): string
    {
        return date('YmdHis') . rand(1000, 9999);
    }

    /**
     * 构建订单VO
     * @param Order $order
     * @param bool $includeDetails
     * @return OrderVO
     */
    private function buildOrderVO(Order $order, bool $includeDetails = false): OrderVO
    {
        $orderVO = new OrderVO();
        $orderVO->setId($order->id);
        $orderVO->setNumber($order->number);
        $orderVO->setStatus($order->status);
        $orderVO->setUserId($order->user_id);
        $orderVO->setAddressBookId($order->address_book_id);
        $orderVO->setOrderTime($order->order_time);
        $orderVO->setCheckoutTime($order->checkout_time ?? '');
        $orderVO->setPayMethod($order->pay_method);
        $orderVO->setPayStatus($order->pay_status);
        $orderVO->setAmount($order->amount);
        $orderVO->setRemark($order->remark ?? '');
        $orderVO->setPhone($order->phone);
        $orderVO->setAddress($order->address);
        $orderVO->setUserName($order->user_name);
        $orderVO->setConsignee($order->consignee);
        $orderVO->setCancelReason($order->cancel_reason ?? '');
        $orderVO->setRejectionReason($order->rejection_reason ?? '');
        $orderVO->setCancelTime($order->cancel_time ?? '');
        $orderVO->setEstimatedDeliveryTime($order->estimated_delivery_time ?? '');
        $orderVO->setDeliveryStatus($order->delivery_status);
        $orderVO->setDeliveryTime($order->delivery_time ?? '');
        $orderVO->setPackAmount($order->pack_amount);
        $orderVO->setTablewareNumber($order->tableware_number);
        $orderVO->setTablewareStatus($order->tableware_status);

        if ($includeDetails) {
            $orderDetails = OrderDetail::where('order_id', $order->id)->get();
            $orderDetailList = [];
            $orderDishesArray = [];
            foreach ($orderDetails as $orderDetail) {
                $orderDetailList[] = [
                    'id' => $orderDetail->id,
                    'name' => $orderDetail->name,
                    'image' => $orderDetail->image  ? get_full_url($orderDetail->image) : '',
                    'dishId' => $orderDetail->dish_id,
                    'setmealId' => $orderDetail->setmeal_id,
                    'dishFlavor' => $orderDetail->dish_flavor,
                    'number' => $orderDetail->number,
                    'amount' => $orderDetail->amount
                ];
                // 构建订单菜品描述字符串
                $dishDescription = $orderDetail->name;
                if ($orderDetail->dish_flavor) {
                    $dishDescription .= '(' . $orderDetail->dish_flavor . ')';
                }
                $dishDescription .= ' x' . $orderDetail->number;
                $orderDishesArray[] = $dishDescription;
            }
            $orderVO->setOrderDetailList($orderDetailList);
            $orderVO->setOrderDishes(implode('; ', $orderDishesArray));
        } else {
            // 如果不需要详情，但需要简单的菜品描述
            $orderDetails = OrderDetail::where('order_id', $order->id)->get();
            $orderDishesArray = [];
            foreach ($orderDetails as $orderDetail) {
                $dishDescription = $orderDetail->name;
                if ($orderDetail->dish_flavor) {
                    $dishDescription .= '(' . $orderDetail->dish_flavor . ')';
                }
                $dishDescription .= ' x' . $orderDetail->number;
                $orderDishesArray[] = $dishDescription;
            }
            $orderVO->setOrderDishes(implode('; ', $orderDishesArray));
        }
        return $orderVO;
    }
}